package com.higgins.eventtracking.client;

import java.util.ArrayList;
import java.util.List;

import com.higgins.eventtracking.client.dto.QuestionDTO;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.Random;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
@SuppressWarnings("deprecation")
public class BrainTrain implements EntryPoint {
	/**
	 * The message displayed to the user when the server cannot be reached or
	 * returns an error.
	 */
	private static final String SERVER_ERROR = "An error occurred while "
			+ "attempting to contact the server. Please check your network "
			+ "connection and try again.";
	
	private final ListBox categoryList = new ListBox();
	private final Label questionText = new Label();
	private RadioButton answerOneRadio = new RadioButton("");
	private RadioButton answerTwoRadio = new RadioButton("");
	private RadioButton answerThreeRadio = new RadioButton("");
	private RadioButton answerFourRadio = new RadioButton("");
	private RadioButton answerFiveRadio = new RadioButton("");

	private final Label errorLabel = new Label();
	
	private final DialogBox dialogBox = new DialogBox();
	private final Button closeButton = new Button("Close");
	private final Label textToServerLabel = new Label();
	private final HTML serverResponseLabel = new HTML();
	private QuestionDTO currentQuestion = null;
	
	private boolean correctAnswer = false;
	private boolean loading = true;
	private Integer selectedAnswer = null;
	private Integer delay = 2000;

	/**
	 * Create a remote service proxy to talk to the server-side Greeting service.
	 */
	private final ELearningTrackingServiceAsync learningService = GWT
			.create(ELearningTrackingService.class);

	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		loadFields();
		createDialogBox();
		createHandlers();
		createRadioButtonHandlers();
		loading = false;
	}
	
	@SuppressWarnings("deprecation")
	private void createRadioButtonHandlers()	{
		answerOneRadio.addClickListener(new ClickListener() {
		    public void onClick(Widget sender) {
		    	if (!loading)	{
		    		sendResponseToServer();
			    	answerTwoRadio.setChecked(false);
			    	answerThreeRadio.setChecked(false);
			    	answerFourRadio.setChecked(false);
			    	answerFiveRadio.setChecked(false);
			    	showCorrectAnswer(0);
			    	Timer timer = new Timer() {
		    		    public void run() {
					    	requestQuestion();
		    		    }
		    		  };
		    		timer.schedule(delay);
		    	}
		    }
		});		
		answerTwoRadio.addClickListener(new ClickListener() {
		    public void onClick(Widget sender) {
		    	if (!loading)	{
		    		sendResponseToServer();
			    	answerOneRadio.setChecked(false);
			    	answerThreeRadio.setChecked(false);
			    	answerFourRadio.setChecked(false);
			    	answerFiveRadio.setChecked(false);
			    	showCorrectAnswer(1);
			    	Timer timer = new Timer() {
		    		    public void run() {
					    	requestQuestion();
		    		    }
		    		  };
		    		timer.schedule(delay);
			    }
		    }
		});		
		answerThreeRadio.addClickListener(new ClickListener() {
		    public void onClick(Widget sender) {
		    	if (!loading)	{
		    		sendResponseToServer();
			    	answerOneRadio.setChecked(false);
			    	answerTwoRadio.setChecked(false);
			    	answerFourRadio.setChecked(false);
			    	answerFiveRadio.setChecked(false);
			    	showCorrectAnswer(2);
			    	Timer timer = new Timer() {
			    		    public void run() {
						    	requestQuestion();
			    		    }
			    		  };
		    		timer.schedule(delay);
		    	}
		    }
		});		
		answerFourRadio.addClickListener(new ClickListener() {
		    public void onClick(Widget sender) {
		    	if (!loading)	{
		    		sendResponseToServer();
			    	answerOneRadio.setChecked(false);
			    	answerTwoRadio.setChecked(false);
			    	answerThreeRadio.setChecked(false);
			    	answerFiveRadio.setChecked(false);
			    	showCorrectAnswer(3);
			    	Timer timer = new Timer() {
		    		    public void run() {
					    	requestQuestion();
		    		    }
		    		  };
		    		timer.schedule(delay);
		    	}
		    }
		});		
		answerFiveRadio.addClickListener(new ClickListener() {
		    public void onClick(Widget sender) {
		    	if (!loading)	{
		    		sendResponseToServer();
			    	answerOneRadio.setChecked(false);
			    	answerTwoRadio.setChecked(false);
			    	answerThreeRadio.setChecked(false);
			    	answerFourRadio.setChecked(false);
			    	showCorrectAnswer(4);
			    	Timer timer = new Timer() {
		    		    public void run() {
					    	requestQuestion();
		    		    }
		    		  };
		    		timer.schedule(delay);
		    	}
		    }
		});		
	}
	
	private void sendResponseToServer() {
		// First, we validate the input.
		errorLabel.setText("");
		/*
		learningService.insertResponse(currentQuestion.getQuestion(), correctAnswer,
				new AsyncCallback<String>() {
					public void onFailure(Throwable caught) {
						// Show the RPC error message to the user
						dialogBox.setText("Remote Procedure Call - Failure");
						serverResponseLabel.addStyleName("serverResponseLabelError");
						serverResponseLabel.setHTML(SERVER_ERROR);
						dialogBox.center();
						dialogBox.setPopupPosition(0, 0);
						closeButton.setFocus(true);
					}

					public void onSuccess(String result) {
						dialogBox.setText("Remote Procedure Call");
						serverResponseLabel.removeStyleName("serverResponseLabelError");
						serverResponseLabel.setHTML(result);
						dialogBox.center();
						dialogBox.setPopupPosition(0, 0);
						closeButton.setFocus(true);
					}
				});
				*/
	}		
	

	private void loadFields()	{
		loadCategoryFields();
		RootPanel.get("categoryList").add(categoryList);
		RootPanel.get("questionText").add(questionText);
		RootPanel.get("answerOneRadio").add(answerOneRadio);
		RootPanel.get("answerTwoRadio").add(answerTwoRadio);
		RootPanel.get("answerThreeRadio").add(answerThreeRadio);
		RootPanel.get("answerFourRadio").add(answerFourRadio);
		RootPanel.get("answerFiveRadio").add(answerFiveRadio);
		RootPanel.get("errorLabelContainer").add(errorLabel);
	}
	private void loadCategoryFields()	{
		categoryList.addItem("------");
		categoryList.addItem("Contract Law");
		categoryList.addItem("Commercial Law");
		categoryList.addItem("Companies Law");
		categoryList.addItem("History");
	}
	
	private void createDialogBox()	{
		// Create the popup dialog box
		dialogBox.setText("Remote Procedure Call");
		dialogBox.setAnimationEnabled(true);
		// We can set the id of a widget by accessing its Element
		closeButton.getElement().setId("closeButton");
		VerticalPanel dialogVPanel = new VerticalPanel();
		dialogVPanel.addStyleName("dialogVPanel");
		dialogVPanel.add(new HTML("<b>Sending name to the server:</b>"));
		dialogVPanel.add(textToServerLabel);
		dialogVPanel.add(new HTML("<br><b>Server replies:</b>"));
		dialogVPanel.add(serverResponseLabel);
		dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
		dialogVPanel.add(closeButton);
		dialogBox.setWidget(dialogVPanel);

		// Add a handler to close the DialogBox
		closeButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				dialogBox.hide();
			}
		});		
	}
	private String getSelectedCategory()	{
		Integer selectedCategory = categoryList.getSelectedIndex();
		return categoryList.getItemText(selectedCategory);
	}
	private void requestQuestion()	{
		// First, we validate the input.
		errorLabel.setText("");
		learningService.retrieveQuestion(getSelectedCategory(),
				new AsyncCallback<QuestionDTO>() {
					public void onFailure(Throwable caught) {
						// Show the RPC error message to the user
						dialogBox.setText("Remote Procedure Call - Failure");
						serverResponseLabel.addStyleName("serverResponseLabelError");
						serverResponseLabel.setHTML(SERVER_ERROR);
						dialogBox.center();
						dialogBox.setPopupPosition(0, 0);
						closeButton.setFocus(true);
					}

					public void onSuccess(QuestionDTO result) {
						errorLabel.setText("");
						currentQuestion = result;
						randomizeAnswers(result);
						questionText.setText(result.getQuestion());
						clearRadioButtons();
						restoreRadioButtonStyleName();
						setAnswers();
					}
				});
	}
	private void randomizeAnswers(QuestionDTO dto)	{
		List<Integer> orderedList = new ArrayList<Integer>();
		orderedList.add(0);
		orderedList.add(1);
		orderedList.add(2);
		orderedList.add(3);
		orderedList.add(4);
		
		int count = 4;
		while (count>-1)	{
			int orderedListIndex = 4-count;
			int selection = Random.nextInt(count+1);
			int answerIndex = orderedList.get(selection);
			dto.addRandomizedAnswer(dto.getAnswer(answerIndex, orderedListIndex));
			orderedList.remove(selection);
			count--;
		}
	}
	private void clearRadioButtons()	{
		answerOneRadio.setChecked(false);
		answerTwoRadio.setChecked(false);
		answerThreeRadio.setChecked(false);
		answerFourRadio.setChecked(false);
		answerFiveRadio.setChecked(false);
	}
	private void setAnswers()	{
		int index = 0;
		answerOneRadio.setText("\t\t\t" + currentQuestion.getRandomizedAnswer(index++));
		answerTwoRadio.setText("\t\t\t" + currentQuestion.getRandomizedAnswer(index++));
		answerThreeRadio.setText("\t\t\t" + currentQuestion.getRandomizedAnswer(index++));
		answerFourRadio.setText("\t\t\t" + currentQuestion.getRandomizedAnswer(index++));
		answerFiveRadio.setText("\t\t\t" + currentQuestion.getRandomizedAnswer(index++));
	}
	private void clearRadioButtonStyleName()	{
		answerOneRadio.setStyleName("incorrectAnswer", false);
		answerTwoRadio.setStyleName("incorrectAnswer", false);
		answerThreeRadio.setStyleName("incorrectAnswer", false);
		answerFourRadio.setStyleName("incorrectAnswer", false);
		answerFiveRadio.setStyleName("incorrectAnswer", false);
		errorLabel.removeStyleName("incorrectAnswer");
		
		answerOneRadio.setStyleName("correctAnswer", false);
		answerTwoRadio.setStyleName("correctAnswer", false);
		answerThreeRadio.setStyleName("correctAnswer", false);
		answerFourRadio.setStyleName("correctAnswer", false);
		answerFiveRadio.setStyleName("correctAnswer", false);
		errorLabel.removeStyleName("correctAnswer");

		answerOneRadio.setStyleName("answer", false);
		answerTwoRadio.setStyleName("answer", false);
		answerThreeRadio.setStyleName("answer", false);
		answerFourRadio.setStyleName("answer", false);
		answerFiveRadio.setStyleName("answer", false);
		errorLabel.removeStyleName("answer");
		
	}
	private void restoreRadioButtonStyleName()	{
		clearRadioButtonStyleName();
		answerOneRadio.setStyleName("answer", true);
		answerTwoRadio.setStyleName("answer", true);
		answerThreeRadio.setStyleName("answer", true);
		answerFourRadio.setStyleName("answer", true);
		answerFiveRadio.setStyleName("answer", true);
		errorLabel.addStyleName("answer");
	}
	private void showCorrectAnswer(Integer selectedAnswer)	{
		int index = 0;
		clearRadioButtonStyleName();
		answerOneRadio.setStyleName(currentQuestion.getCorrectAnswer().equals(index++)?"correctAnswer":"incorrectAnswer", true);
		answerTwoRadio.setStyleName(currentQuestion.getCorrectAnswer().equals(index++)?"correctAnswer":"incorrectAnswer", true);
		answerThreeRadio.setStyleName(currentQuestion.getCorrectAnswer().equals(index++)?"correctAnswer":"incorrectAnswer", true);
		answerFourRadio.setStyleName(currentQuestion.getCorrectAnswer().equals(index++)?"correctAnswer":"incorrectAnswer", true);
		answerFiveRadio.setStyleName(currentQuestion.getCorrectAnswer().equals(index++)?"correctAnswer":"incorrectAnswer", true);
		errorLabel.setText(currentQuestion.getCorrectAnswer().equals(selectedAnswer)?"CORRECT!!!":"WRONG!!!");
		errorLabel.addStyleName(currentQuestion.getCorrectAnswer().equals(selectedAnswer)?"correctAnswer":"incorrectAnswer");
	}
	private void createHandlers()	{
		// Create a handler for the sendButton and nameField
		class MyHandler implements ChangeHandler {
			@Override
			public void onChange(ChangeEvent event) {
				requestQuestion();
			}
		}	
		MyHandler handler = new MyHandler();
		categoryList.addChangeHandler(handler);
	}
}
